 
/**
 * @file    app_uart.c
 * @author  Azolla (1228449928@qq.com)
 * @brief   led contorl PWM
 * @version 0.1
 * @date    2022-12-06
 * 
 * @copyright Copyright (c) 2022
 * */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "driver/uart.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "sdkconfig.h"
 
#include "app_uart.h"

 
#define TAG "app_uart"

// Note: Some pins on target chip cannot be assigned for UART communication.
// Please refer to documentation for selected board and target to configure pins using Kconfig.
 
#define UART_BUFF_SIZE      (128)
 
// Timeout threshold for UART = number of symbols (~10 tics) with unchanged state on receive pin
#define UART_READ_TOUT      (3) // 3.5T * 8 = 28 ticks, TOUT=3 -> ~24..33 ticks

static const uart_port_t uart_port = UART_NUM_0;

//================================================================================================= 
//================================================================================================= 
// static QueueHandle_t write_queue = NULL;      // 队列
// if (xQueueReceive(write_queue, &info, 2000) == pdTRUE) { 
// xQueueSend(write_queue, &info, (TickType_t)100);  // 发送队列数据
//  write_queue = xQueueCreate(3, sizeof(mqtt_data_t));

static uart_func_t  uart_callback_func = NULL; 

static void uart_register_callback(uart_func_t callback_func)
{
    uart_callback_func = callback_func;
}

void uart0_sendto_bytes(const uint8_t *data, uint8_t len)
{
    if (uart_write_bytes(uart_port, data, len) != len) {
        // add your code to handle sending failure here
    } else {
        ESP_ERROR_CHECK( uart_wait_tx_done(uart_port, 20) );  
    }
}
 
static void uart0_driver_init(void)
{
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity    = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk= UART_SCLK_APB,
    };
 
    // Install UART driver (we don't need an event queue here)
    // In this example we don't even use a buffer for sending data.
    ESP_ERROR_CHECK(uart_driver_install(uart_port, UART_BUFF_SIZE * 2, 0, 0, NULL, 0));

    // Configure UART parameters
    ESP_ERROR_CHECK(uart_param_config(uart_port, &uart_config));
}

static void uart_read_task(void *arg)
{
    uart_port_t uart_port = *((uint8_t *)arg) - '0';
    // ESP_LOGI(TAG, "UART[%d] start recieve loop.\r\n", uart_port);
 
    // Allocate buffers for UART
    uint8_t *data = (uint8_t *)malloc(UART_BUFF_SIZE);
    assert(data != NULL);
 
    while ( true ) {
        // Read data from UART
        int len = uart_read_bytes(uart_port, data, UART_BUFF_SIZE, 100 / portTICK_RATE_MS);
        // Write data back to UART
        if (len > 0) {
            // ESP_LOGI(TAG, "Received %u bytes:", len);
            if (uart_callback_func != NULL) {
                uart_callback_func(uart_port, data, len);
            }
        }  
    }
    vTaskDelete(NULL);
}


// uart_port_t uart_port = UART_NUM_1;
void app_uart_init(uart_func_t callback_func)
{
    uart_register_callback(callback_func);

#if 1  // debug
    uart0_driver_init();
    xTaskCreatePinnedToCore(uart_read_task, "uart0_task", 3 * 1024, (void * const)"0", 5, NULL, APP_CPU_NUM);  
#endif   
}
